package com.meida.module.bus.provider.service.impl;

import com.alibaba.fastjson.util.TypeUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.meida.common.mybatis.base.service.impl.BaseServiceImpl;
import com.meida.common.mybatis.entity.EntityMap;
import com.meida.common.mybatis.model.PageParams;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.query.CriteriaDelete;
import com.meida.common.mybatis.query.CriteriaQuery;
import com.meida.common.mybatis.query.CriteriaSave;
import com.meida.common.mybatis.query.CriteriaUpdate;
import com.meida.common.security.OpenHelper;
import com.meida.common.utils.FlymeUtils;
import com.meida.module.admin.client.entity.BaseUser;
import com.meida.module.admin.provider.service.BaseUserService;
import com.meida.module.bus.client.entity.*;
import com.meida.module.bus.client.vo.BusProjectVo;
import com.meida.module.bus.provider.api.service.SyncOAService;
import com.meida.module.bus.provider.api.util.ApiConstants;
import com.meida.module.bus.provider.mapper.BusProjectMapper;
import com.meida.module.bus.provider.service.BusDeptService;
import com.meida.module.bus.provider.service.BusProjectService;
import com.meida.module.bus.provider.service.BusUserProjectService;
import com.meida.module.bus.provider.service.BusVersionService;
import com.meida.module.bus.provider.utils.MyFlymeUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 项目表接口实现类
 *
 * @author flyme
 * @date 2020-09-25
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class BusProjectServiceImpl extends BaseServiceImpl<BusProjectMapper, BusProject> implements BusProjectService {

    @Autowired
    private BaseUserService baseUserService;

    @Autowired
    private BusVersionService busVersionService;

    @Autowired
    private BusUserProjectService busUserProjectService;

    @Autowired
    private BusDeptService busDeptService;

    @Autowired
    private SyncOAService syncOAService;

    @Override
    public ResultBody beforeAdd(CriteriaSave cs, BusProject project, EntityMap extra) {
        project.setReportOutState(0);
        return ResultBody.ok();
    }


    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<BusProject> cq, BusProject project, EntityMap requestMap) {
        Boolean isReport = TypeUtils.castToBoolean(requestMap.get("isReport"));
        if (FlymeUtils.isEmpty(isReport)) {
            isReport = false;
        }
        cq.select("project.projectId,user.userName,concat(version.bigVersion,'.',version.smallVerion) as bigVersion,reportOutType");
        cq.createJoin(BaseUser.class).setMainField("userId").setJoinField("userId");
        if (isReport) {
            cq.isNotNull("project.versionpackageId");
            cq.createJoin(BusVersion.class).setMainField("versionpackageId").setJoinField("versionId");
            cq.eq("bigVersion", ApiConstants.VER_200);
        } else {
            cq.createJoin(BusVersion.class).setMainField("versionId").setJoinField("versionId");
        }
        cq.like(BusProject.class, "projectName");
        cq.like(BusProject.class, "projectCode");
        cq.orderByDesc("project.createTime");
        return ResultBody.ok();
    }


//
//    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
//    public ResultBody purchasePageList(CriteriaQuery<BusProject> cq, BusProject project, EntityMap requestMap) {
//        cq.select("user.userName,version.bigVersion");
//        cq.createJoin(BusVersion.class).setMainField("versionId").setJoinField("versionId");
//        cq.createJoin(BaseUser.class).setMainField("userId").setJoinField("userId");
//        cq.like(BusProject.class,"projectName");
//        cq.orderByDesc("project.createTime");
//        return ResultBody.ok();
//    }

    @Override
    public List<String> getProjectCodes(Long userId) {
        return baseMapper.getProjectCodes(userId);
    }

    /**
     * 查询所有项目以及版本和创建人并分页
     *
     * @param params
     * @return
     */
    @Override
    public ResultBody pageList2(Map params) {

        List<BusProject> busProjects;
        String projectCode = (String) params.get("projectCode");
        String projectName = (String) params.get("projectName");
        if (StringUtils.isEmpty(projectName) && StringUtils.isEmpty(projectCode)) {
            busProjects = baseMapper.selectList(new QueryWrapper<BusProject>().orderByDesc("createTime"));
        } else if (projectCode != null && StringUtils.isEmpty(projectName)) {
            busProjects = baseMapper.selectList(new QueryWrapper<BusProject>().eq("projectCode", projectCode).orderByDesc("createTime"));
        } else if (projectName != null && StringUtils.isEmpty(projectCode)) {
            busProjects = baseMapper.selectList(new QueryWrapper<BusProject>().eq("projectName", projectName).orderByDesc("createTime"));
        } else {
            busProjects = baseMapper.selectList(new QueryWrapper<BusProject>().eq("projectCode", projectCode).eq("projectName", projectName).orderByDesc("createTime"));
        }
        PageParams page = new PageParams();

        long pageNo = Long.parseLong(params.get("page").toString());
        int pageSize = Integer.parseInt(params.get("limit").toString());


        List<BusProjectVo> s = busProjects.stream().map((map) -> {
            BusProjectVo vo = new BusProjectVo();
            BeanUtils.copyProperties(map, vo);
            //查询提交人
            BaseUser baseuser = baseUserService.getUserById(map.getUserId());
            if (!StringUtils.isEmpty(baseuser)) {
                vo.setFounder(baseuser.getNickName());
            } else {
                vo.setFounder(null);
            }

            //查询项目对应的版本
            BusVersion version = busVersionService.getOne(new QueryWrapper<BusVersion>().eq("projectId", map.getProjectId()));
            if (StringUtils.isEmpty(version)) {
                vo.setVersion("还没有对应版本");
            } else {
                vo.setVersion(version.getBigVersion().toString() + "." + version.getSmallVerion().toString());
            }

            Date time = version.getUpdateTime();
            if (StringUtils.isEmpty(time)) {
                time = version.getCreateTime();
            }
            vo.setUpdateTime(time);
            return vo;
        }).collect(Collectors.toList());

        ResultBody result = new ResultBody();
        page.setPages(pageNo);
        page.setSize(pageSize);
        page.setLimit(pageSize);
        page.setCurrent(pageNo);
        page.setRecords(s);
        Integer total = baseMapper.selectCount(new QueryWrapper<>());
        page.setTotal(total);
        return result.ok().data(page);
    }

    @Override
    public List<EntityMap> initData(Map map) {
        CriteriaQuery<BusProject> cq = new CriteriaQuery(BusProject.class);
        cq.select(" project.projectName,project.projectCode,project.createTime,project.updateTime,project.userId,(CASE project.state WHEN 1 THEN '是' ELSE '否' END) as state,user.userName,concat(version.bigVersion,'.',version.smallVerion) as bigVersion");
        cq.createJoin(BaseUser.class).setMainField("userId").setJoinField("userId");
        cq.createJoin(BusVersion.class).setMainField("versionId").setJoinField("versionId");
        cq.like(BusProject.class, "projectName");
        cq.like(BusProject.class, "projectCode");
        cq.orderByDesc("project.createTime");
        return selectEntityMap(cq);
    }

    @Override
    public ResultBody purchasePageList(Map params) {
        Long userId = OpenHelper.getUserId();
        List<String> userProjectIds = getUserProjectIds(userId);
        List<String> userDeptList = busDeptService.getUserDepts(userId);
        CriteriaQuery<BusProject> cq = new CriteriaQuery(params, BusProject.class);
        cq.select("project.*,user.userName,concat(version.bigVersion,'.',version.smallVerion) as bigVersion,version.updateTime");
        cq.createJoin(BusVersion.class).setMainField("versionId").setJoinField("versionId");
        cq.createJoin(BaseUser.class).setMainField("userId").setJoinField("userId");
        cq.like(BusProject.class, "projectName");
        cq.like(BusProject.class, "projectCode");
        cq.isNotNull("project.versionId");
        cq.orderByDesc("project.createTime");
        cq.orderByDesc("version.createTime");
        if (FlymeUtils.isNotEmpty(userProjectIds)) {
            cq.in("project.projectId", userProjectIds);
        }
        if (userDeptList.size() > 0) {
            if (!userDeptList.contains("M00")) {
                cq.apply("replace(project.deptProjectCode,',','|') regexp {0}", org.thymeleaf.util.StringUtils.join(userDeptList, "|"));
            }
        }
        return basePageList(cq);
    }

    @Override
    public ResultBody updateProjectStus(Long projectId, Integer status) {
        CriteriaUpdate<BusProject> cu = new CriteriaUpdate<>();
        cu.set("state", status);
        cu.eq("projectId", projectId);
        boolean a = update(cu);
        return ResultBody.ok();
    }

    @Override
    public BusProject findByProjectCode(String projectCode) {
        CriteriaQuery<BusProject> cq = new CriteriaQuery(BusProject.class);
        cq.eq("projectCode", projectCode);
        return getOne(cq);
    }

    @Override
    public void saveUserProjects(Long userId, String... projectIds) {
        if (userId == null || projectIds == null) {
            return;
        }
        BaseUser user = baseUserService.getUserById(userId);
        if (user == null) {
            return;
        }
        // 先清空,在添加
        removeProjects(userId);
        if (projectIds.length > 0) {
            for (String projectId : projectIds) {
                BusUserProject busUserProject = new BusUserProject();
                busUserProject.setUserId(userId);
                busUserProject.setProjectId(Long.parseLong(projectId));
                busUserProjectService.save(busUserProject);
            }
            List<String> projectIdList = Arrays.asList(projectIds);
            String redisKey = "userProjectIds_" + userId;
            String projectIdsStr = FlymeUtils.listToString(projectIdList, ',');
            redisUtils.set(redisKey, projectIdsStr);
        }
    }

    @Override
    public void saveDeptProjects(Long projectId, String... deptIds) {
        if (projectId == null || deptIds == null) {
            return;
        }
        String deptId = "";
        if (FlymeUtils.isNotEmpty(deptIds)) {
            for (String strs : deptIds) {
                BusDept dept = busDeptService.getById(Long.parseLong(strs));
                if (FlymeUtils.isNotEmpty(deptId)) {
                    deptId = deptId + "," + dept.getDeptCode();
                } else {
                    deptId = dept.getDeptCode();
                }

            }
        }
        BusProject project = getById(projectId);
        project.setDeptProjectCode(deptId);
        saveOrUpdate(project);
    }

    @Override
    public ResultBody getDeptProjects(Long projectId) {
        EntityMap entityMap = new EntityMap();
        BusProject project = getById(projectId);
        List<String> depts = new ArrayList<>();
        List<Long> deptIds = new ArrayList<>();
        String deptCode = project.getDeptProjectCode();
        if (FlymeUtils.isNotEmpty(deptCode)) {
            String[] strings = deptCode.split(",");
            for (String str : strings) {
                depts.add(str);
            }
        }
        CriteriaQuery<BusDept> deptCriteriaQuery = new CriteriaQuery<BusDept>(BusDept.class);
        deptCriteriaQuery.select("deptId");
        if (FlymeUtils.isNotEmpty(depts)) {
            deptCriteriaQuery.in("deptCode", depts);
        } else {
            deptCriteriaQuery.eq("deptCode", "2");
        }
        List<BusDept> busDeptList = busDeptService.list(deptCriteriaQuery);
        for (BusDept dept : busDeptList) {
            deptIds.add(dept.getDeptId());
        }
        entityMap.put("deptList", busDeptService.getAllDept());
        entityMap.put("deptIds", deptIds);
        return ResultBody.ok(entityMap);
    }

    @Override
    public void removeProjectdepts(Long deptId) {

    }

    @Override
    public void removeProjects(Long userId) {
        CriteriaDelete cd = new CriteriaDelete();
        String redisKey = "userProjectIds_" + userId;
        redisUtils.del(redisKey);
        cd.eq("userId", userId);
        busUserProjectService.remove(cd);
    }

    @Override
    public List<String> getUserProjectIds(Long userId) {
        List<String> projectIdList = Lists.newArrayList();
        String redisKey = "userProjectIds_" + userId;
        if (redisUtils.hasKey(redisKey)) {
            String projectIdsStr = redisUtils.getString(redisKey);
            projectIdList = MyFlymeUtils.stringToList(projectIdsStr);
        } else {
            CriteriaQuery<BusUserProject> cq = new CriteriaQuery(BusUserProject.class);
            cq.select("projectId");
            cq.eq("userId", userId);
            List<EntityMap> entityMapList = selectEntityMap(cq);
            projectIdList = entityMapList.stream().map(entityMap -> entityMap.get("projectId").toString()).collect(Collectors.toList());
            if (FlymeUtils.isNotEmpty(projectIdList)) {
                String projectIdsStr = FlymeUtils.listToString(projectIdList, ',');
                redisUtils.set(redisKey, projectIdsStr);
            }
        }
        return projectIdList;
    }

    @Override
    public ResultBody getUserProjectList(Long userId) {
        CriteriaQuery cq = new CriteriaQuery(BusProject.class);
        cq.select(BusProject.class, "projectId", "projectName");
        List<EntityMap> projectList = selectEntityMap(cq);
        List<String> projectIds = getUserProjectIds(userId);
        EntityMap map = new EntityMap();
        map.put("projectList", projectList);
        map.put("projectIds", projectIds);
        return ResultBody.ok(map);
    }

    @Override
    public EntityMap getProjectInfo(Long projectId) {
        CriteriaQuery cq = new CriteriaQuery(BusProject.class);
        cq.select(BusProject.class, "projectId", "projectName");
        cq.select(BusVersion.class, "createTime");
        cq.eq(BusProject.class, "projectId", projectId);
        cq.createJoin(BusVersion.class).setMainField("versionpackageId").setJoinField("versionId");
        return findOne(cq);
    }

    @Override
    public ResultBody setReportOutStateCheck(Long projectId) {
        BusProject busProject = getById(projectId);
        Integer state = FlymeUtils.getInteger(busProject.getState(), 0);
        if (state == 1) {
            return ResultBody.failed("项目已锁定");
        }
        Integer reportOutType = busProject.getReportOutType();
        if (FlymeUtils.isEmpty(reportOutType)) {
            return ResultBody.failed("未分配对外月报样式");
        }
        Integer reportOutState = FlymeUtils.getInteger(busProject.getReportOutState(), 0);
        if (reportOutState != 0) {
            return ResultBody.failed("已提交oa审核,请不要重复提交");
        }
        String userName = OpenHelper.getUserName();
        String approvalUrl = "";
        if (reportOutType == 1) {
            approvalUrl = "/approvl/reportOut1Detail";
        }
        if (reportOutType == 2) {
            approvalUrl = "/approvl/reportOut2Detail";
        }
        if (reportOutType == 3) {
            approvalUrl = "/approvl/reportOut3Detail";
        }
        if (reportOutType == 4) {
            approvalUrl = "/approvl/reportOut4Detail";
        }
        if (reportOutType == 5) {
            approvalUrl = "/approvl/reportOut5Detail";
        }
        syncOAService.approval("", approvalUrl, userName, ApiConstants.BUSINESS_APPROVAL_REPORT_OUT, projectId.toString());
        //更新项目对外状态为审核中
        updateReportOutState(projectId, 1);
        return ResultBody.ok("提交成功,请等待审核");
    }

    @Override
    public Boolean updateReportOutState(Long projectId, Integer reportOutState) {
        CriteriaUpdate<BusProject> cu = new CriteriaUpdate();
        cu.eq("projectId", projectId);
        cu.set("reportOutState", reportOutState);
        return update(cu);
    }
}
